#include <Windows.h>
#include <mmsystem.h>
#include <d3dx9.h>
#pragma warning( disable : 4996 ) // disable deprecated warning 
#include <strsafe.h>
#pragma warning( default : 4996 ) 

#pragma warning( disable : 4996 ) // disable deprecated warning 
#pragma warning( disable : 4244 ) // disable deprecated warning 
#pragma warning( disable : 4995 ) // disable deprecated warning 



#include <vector>
using namespace std;


//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D       = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; // Buffer to hold vertices
LPDIRECT3DINDEXBUFFER9  g_pIB        = NULL;
LPDIRECT3DTEXTURE9      g_pTexture   = NULL; // Our texture

ID3DXEffect* g_pEffect = NULL ;

bool		fullscreen=TRUE;	
#define		MAP_SIZE	  1024							// Size Of Our .RAW Height Map (NEW)
#define		STEP_SIZE	  16							// Width And Height Of Each Quad (NEW)
#define		HEIGHT_RATIO  1.5f							// Ratio That The Y Is Scaled According To The X And Z (NEW)

BYTE g_HeightMap[MAP_SIZE*MAP_SIZE];					// Holds The Height Map Data (NEW)

float scaleValue = 0.15f;								// Scale Value For The Terrain (NEW)

D3DXVECTOR3 g_eyePos;
D3DXVECTOR3 g_eyeAt;
typedef unsigned long uint32; 


#define  useTotalMap


D3DXMATRIXA16 g_matWorldViewProjection;

D3DXMATRIXA16 g_matWorld;
D3DXMATRIXA16 g_matView;
D3DXMATRIXA16 g_matProj;

int g_nGrads = 5;

// A structure for our custom vertex type. We added texture coordinates
struct CUSTOMVERTEX
{
	D3DXVECTOR3 position; // The position
	D3DCOLOR    color;    // The color
	FLOAT       tu, tv;   // The texture coordinates
};

struct SINDEX 
{
	int v0;
	int v1;
	int v2;
};

vector<CUSTOMVERTEX> g_listVertex;
vector<SINDEX>       g_listIndex;

vector<CUSTOMVERTEX> g_listLineVertex;


// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)


bool g_bWireFrame = false;

enum EWorkState
{
	E_CONTOUR_LINE,
	E_CROSS_SECTION,
	E_VERTICAL_SECTION,
	E_Color,
	E_ONLY_CONTOURLINE
};

EWorkState g_WorkState = E_CONTOUR_LINE;

ID3DXEffect* g_pCrossEffect = NULL ;
ID3DXEffect* g_pVerticalEffect = NULL ;
ID3DXEffect* g_pColorEffect = NULL ;
ID3DXEffect* g_pONLY = NULL ;




int          g_nDivision = 5;


// Loads The .RAW File And Stores It In pHeightMap
void LoadRawFile(LPSTR strName, int nSize, BYTE *pHeightMap)
{
	FILE *pFile = NULL;

	// Open The File In Read / Binary Mode.
	pFile = fopen( strName, "rb" );

	// Check To See If We Found The File And Could Open It
	if ( pFile == NULL )	
	{
		// Display Error Message And Stop The Function
		MessageBox(NULL, L"Can't Find The Height Map!", L"Error", MB_OK);
		return;
	}

	fread( pHeightMap, 1, nSize, pFile );

	// After We Read The Data, It's A Good Idea To Check If Everything Read Fine
	int result = ferror( pFile );

	// Check If We Received An Error
	if (result)
	{
		MessageBox(NULL, L"Failed To Get Data!", L"Error", MB_OK);
	}

	// Close The File.
	fclose(pFile);
}

int Height(BYTE *pHeightMap, int X, int Y)				// This Returns The Height From A Height Map Index
{
	int x = X % MAP_SIZE;								// Error Check Our x Value
	int y = Y % MAP_SIZE;								// Error Check Our y Value

	if(!pHeightMap) return 0;							// Make Sure Our Data Is Valid

	return pHeightMap[x + (y * MAP_SIZE)];				// Index Into Our Height Array And Return The Height
}

int getVertexColor(BYTE *pHeightMap, int x, int y)		// Sets The Color Value For A Particular Index, Depending On The Height Index
{
	int iColor = 0;
	if(!pHeightMap) return iColor;								// Make Sure Our Height Data Is Valid

	iColor = int((-0.15f + (Height(pHeightMap, x, y ) / 256.0f)) * 256);

	return iColor;
}

void initVertex()
{
	int X = 0, Y = 0;									// Create Some Variables To Walk The Array With.
	int x, y, z;										// Create Some Variables For Readability

	BYTE *pHeightMap = g_HeightMap;

	CUSTOMVERTEX v0;
	CUSTOMVERTEX v1;
	CUSTOMVERTEX v2;
	CUSTOMVERTEX v3;

	SINDEX tri0;
	SINDEX tri1;


	for ( X = 0; X < (MAP_SIZE-STEP_SIZE); X += STEP_SIZE )
		for ( Y = 0; Y < (MAP_SIZE-STEP_SIZE); Y += STEP_SIZE )
		{
			// Get The (X, Y, Z) Value For The Bottom Left Vertex
			x = X;							
			y = Height(pHeightMap, X, Y );	
			z = Y;

			v0.position.x = x;
			v0.position.y = y;
			v0.position.z = z;
			v0.color = D3DCOLOR_RGBA( 0, 0, getVertexColor( pHeightMap, x, z ), 0);
#ifdef useTotalMap
			v0.tu = float((float)x/MAP_SIZE) ;
			v0.tv = float((float)z/MAP_SIZE);
#else
			v0.tu = 0.0f;
			v0.tv = 0.0f;
#endif


			// Get The (X, Y, Z) Value For The Top Left Vertex
			x = X;										
			y = Height(pHeightMap, X, Y + STEP_SIZE );  
			z = Y + STEP_SIZE ;							

			v1.position.x = x;
			v1.position.y = y;
			v1.position.z = z;

			v1.color = D3DCOLOR_RGBA( 0, 0, getVertexColor( pHeightMap, x, z ), 0);

#ifdef useTotalMap
			v1.tu = float((float)x/MAP_SIZE);
			v1.tv = float((float)z/MAP_SIZE);
#else
			v1.tu = 0.0f;
			v1.tv = 1.0f;
#endif


			// Get The (X, Y, Z) Value For The Top Right Vertex
			x = X + STEP_SIZE; 
			y = Height(pHeightMap, X + STEP_SIZE, Y + STEP_SIZE ); 
			z = Y + STEP_SIZE ;

			v2.position.x = x;
			v2.position.y = y;
			v2.position.z = z;

			v2.color = D3DCOLOR_RGBA( 0, 0, getVertexColor( pHeightMap, x, z ), 0);



#ifdef useTotalMap
			v2.tu = float((float)x/MAP_SIZE);
			v2.tv = float((float)z/MAP_SIZE) ;
#else
			v2.tu = 1.0f;
			v2.tv = 1.0f;
#endif
			// Get The (X, Y, Z) Value For The Bottom Right Vertex
			x = X + STEP_SIZE; 
			y = Height(pHeightMap, X + STEP_SIZE, Y ); 
			z = Y;

			v3.position.x = x;
			v3.position.y = y;
			v3.position.z = z;

			v3.color = D3DCOLOR_RGBA( 0, 0, getVertexColor( pHeightMap, x, z ), 0);

#ifdef useTotalMap
			v3.tu = float((float)x/MAP_SIZE);
			v3.tv = float((float)z/MAP_SIZE);
#else
			v3.tu = 1.0f;
			v3.tv = 0.0f;
#endif
			int _firstIdx = g_listVertex.size();

			g_listVertex.push_back( v0 );
			g_listVertex.push_back( v1 );
			g_listVertex.push_back( v2 );
			g_listVertex.push_back( v3 );

			tri0.v0 = _firstIdx;
			tri0.v1 = _firstIdx+1;
			tri0.v2 = _firstIdx+2;

			tri1.v0 = _firstIdx+2;
			tri1.v1 = _firstIdx+3;
			tri1.v2 = _firstIdx;

			g_listIndex.push_back( tri0 );
			g_listIndex.push_back( tri1 );

		}
}

//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
	// Create the D3D object.
	if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
		return E_FAIL;

	// Set up the structure used to create the D3DDevice. Since we are now
	// using more complex geometry, we will create a device with a zbuffer.
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory( &d3dpp, sizeof(d3dpp) );
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	d3dpp.EnableAutoDepthStencil = TRUE;
	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

	// Create the D3DDevice
	if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp, &g_pd3dDevice ) ) )
	{
		return E_FAIL;
	}

	// Turn off culling
	g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

	// Turn off D3D lighting
	g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

	// Turn on the zbuffer
	g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

	LoadRawFile("Data/Terrain.raw", MAP_SIZE * MAP_SIZE, g_HeightMap);	// (NEW)

	g_eyePos = D3DXVECTOR3( -256.0f, 1194.0f,512.0f  );
	g_eyeAt  = D3DXVECTOR3( 0.0f, 0.0f,512.0f  );


	return S_OK;
}


int getVertexByHeight( int height, vector<CUSTOMVERTEX> &listVertex)
{
	for( size_t i=0; i<g_listVertex.size(); i++)
	{
		if( g_listVertex[i].position.y == height )
		{
			CUSTOMVERTEX rr = g_listVertex[i];
			bool isExist = false;
			for( size_t j=0; j<listVertex.size(); j++)
			{
				if( listVertex[j].position == rr.position )
					isExist = true;
			}
			if( !isExist)
				listVertex.push_back( g_listVertex[i] );
		}
	}
	return listVertex.size();
}

//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: Create the textures and vertex buffers
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
	initVertex();

	DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE ;
	D3DXCreateEffectFromFile( g_pd3dDevice, L"mm.fx", NULL, NULL, dwShaderFlags, NULL, &g_pEffect, NULL );
	D3DXCreateEffectFromFile( g_pd3dDevice, L"cross.fx", NULL, NULL, dwShaderFlags, NULL, &g_pCrossEffect, NULL );
	D3DXCreateEffectFromFile( g_pd3dDevice, L"vertical.fx", NULL, NULL, dwShaderFlags, NULL, &g_pVerticalEffect, NULL );
	
	D3DXCreateEffectFromFile( g_pd3dDevice, L"color.fx", NULL, NULL, dwShaderFlags, NULL, &g_pColorEffect, NULL );
	D3DXCreateEffectFromFile( g_pd3dDevice, L"only.fx", NULL, NULL, dwShaderFlags, NULL, &g_pONLY, NULL );


	// Use D3DX to create a texture from a file based image
	if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"hangpai.tga", &g_pTexture ) ) )
	{
		// If texture is not in current folder, try parent folder
		if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"..\\hangpai.tga", &g_pTexture ) ) )
		{
			MessageBox(NULL, L"Could not find banana.bmp", L"HeightMap.exe", MB_OK);
			return E_FAIL;
		}
	}

	size_t nVertexNum = g_listVertex.size();
	// Create the vertex buffer.
	if( FAILED( g_pd3dDevice->CreateVertexBuffer( nVertexNum * sizeof(CUSTOMVERTEX),
		0, D3DFVF_CUSTOMVERTEX,
		D3DPOOL_MANAGED, &g_pVB, NULL ) ) )
	{
		return E_FAIL;
	}

	// Fill the vertex buffer. We are setting the tu and tv texture
	// coordinates, which range from 0.0 to 1.0
	CUSTOMVERTEX* pVertices;
	if( FAILED( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) )
		return E_FAIL;
	for( DWORD i=0; i<nVertexNum; i++ )
	{
		pVertices[i].position = g_listVertex[i].position;
		pVertices[i].color    = g_listVertex[i].color;
		pVertices[i].tu       = g_listVertex[i].tu;
		pVertices[i].tv       = g_listVertex[i].tv;

	}
	g_pVB->Unlock();

	size_t _triNum = g_listIndex.size() ;
	if( FAILED( g_pd3dDevice->CreateIndexBuffer( _triNum * 3 *sizeof(uint32),
		D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_MANAGED, 
		&g_pIB, NULL ) ) )
		return E_FAIL;

	uint32* pIndices;

	int size = _triNum * 3 *sizeof(uint32);

	if( FAILED( g_pIB->Lock( 0,	size, (void**)&pIndices, 0 ) ) )            // Send default flags to the lock
	{
		//		SAFE_RELEASE(g_pIB);
		return E_FAIL;
	}


	for ( size_t i=0; i<g_listIndex.size(); i++ )
	{
		int j = i*3;
		pIndices[j] = g_listIndex[i].v0;
		pIndices[j+1] = g_listIndex[i].v1;
		pIndices[j+2] = g_listIndex[i].v2;

	}

	g_pIB->Unlock();
	return S_OK;
}


//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{

	if (fullscreen)										// Are We In Fullscreen Mode?
	{
		ChangeDisplaySettings(NULL,0);					// If So Switch Back To The Desktop
		ShowCursor(TRUE);								// Show Mouse Pointer
	}

	if( g_pTexture != NULL )
		g_pTexture->Release();

	if( g_pVB != NULL )
		g_pVB->Release();

	if( g_pd3dDevice != NULL )
		g_pd3dDevice->Release();

	if( g_pD3D != NULL )
		g_pD3D->Release();
}



//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: Sets up the world, view, and projection transform matrices.
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{
	// Set up world matrix
	D3DXMATRIXA16 matWorld;
	D3DXMatrixIdentity( &matWorld );

	//	D3DXMatrixScaling( &matWorld, scaleValue, scaleValue, scaleValue);
	//D3DXMatrixRotationX( &matWorld, timeGetTime()/1000.0f );


	g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

	// Set up our view matrix. A view matrix can be defined given an eye point,
	// a point to lookat, and a direction for which way is up. Here, we set the
	// eye five units back along the z-axis and up three units, look at the
	// origin, and define "up" to be in the y-direction.
	D3DXVECTOR3 vEyePt( 312.0f, 194.0f,10.0f );
	D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
	D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
	D3DXMATRIXA16 matView;

	vEyePt = g_eyePos;
	vLookatPt = g_eyeAt;

	D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
	g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

	// For the projection matrix, we set up a perspective transform (which
	// transforms geometry from 3D view space to 2D viewport space, with
	// a perspective divide making objects smaller in the distance). To build
	// a perpsective transform, we need the field of view (1/4 pi is common),
	// the aspect ratio, and the near and far clipping planes (which define at
	// what distances geometry should be no longer be rendered).
	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 10000.0f );
	g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

	g_matWorld = matWorld;
	g_matView  = matView;
	g_matProj  = matProj;
}




//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
	// Clear the backbuffer and the zbuffer
	g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
		D3DCOLOR_XRGB(255,255,255), 1.0f, 0 );

	if( g_bWireFrame )
		g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME);
	else
		g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID);

	g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE);

	g_pd3dDevice->SetTexture( 0, g_pTexture );
	//g_pd3dDevice->SetTexture( 0, NULL );

	//g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1  );
	//g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
	//g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
	//g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG2 );

	//g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
	//g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );

	g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);  

	g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);

	g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
	g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);

	g_pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);


	// Render the vertex buffer contents
	g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
	g_pd3dDevice->SetIndices( g_pIB );

	g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
	//g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 63*63*2 );
	//g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 63*63*2 );


	UINT iPass, cPasses;
	// Begin the scene
	if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
	{
		// Setup the world, view, and projection matrices
		SetupMatrices();

		switch( g_WorkState )
		{
		case E_CROSS_SECTION:
			{
				g_pCrossEffect->SetMatrix( "matViewProjection", &g_matProj ) ;
				g_pCrossEffect->SetMatrix( "matWorld", &g_matWorld ) ;
				g_pCrossEffect->SetMatrix("matView", &g_matView );
				g_pCrossEffect->SetTechnique( "vs_2_0_ps_2_0" );
				g_pCrossEffect->SetTexture("diffuseMap", g_pTexture );
				g_pCrossEffect->SetInt( "g_nDivision", g_nDivision );

				// Apply the technique contained in the effect 
				g_pCrossEffect->Begin(&cPasses, 0) ;

				for (iPass = 0; iPass < cPasses; iPass++)
				{
					g_pCrossEffect->BeginPass(iPass) ;

					g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 
						g_listVertex.size(), 0, g_listIndex.size() );


					g_pCrossEffect->EndPass();
				}
				g_pCrossEffect->End() ;
			}
			break;
		case E_CONTOUR_LINE:
			{
				g_pEffect->SetMatrix( "matViewProjection", &g_matProj ) ;
				g_pEffect->SetMatrix( "matWorld", &g_matWorld ) ;
				g_pEffect->SetMatrix("matView", &g_matView );
				g_pEffect->SetTechnique( "vs_2_0_ps_2_0" );
				g_pEffect->SetTexture("diffuseMap", g_pTexture );
				g_pEffect->SetInt( "g_nGrads", g_nGrads );

				// Apply the technique contained in the effect 
				g_pEffect->Begin(&cPasses, 0) ;

				for (iPass = 0; iPass < cPasses; iPass++)
				{
					g_pEffect->BeginPass(iPass) ;

					g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 
						g_listVertex.size(), 0, g_listIndex.size() );


					g_pEffect->EndPass();
				}
				g_pEffect->End() ;
			}
			break;
		case E_VERTICAL_SECTION:
			{
				g_pVerticalEffect->SetMatrix( "matViewProjection", &g_matProj ) ;
				g_pVerticalEffect->SetMatrix( "matWorld", &g_matWorld ) ;
				g_pVerticalEffect->SetMatrix("matView", &g_matView );
				g_pVerticalEffect->SetTechnique( "vs_2_0_ps_2_0" );
				g_pVerticalEffect->SetTexture("diffuseMap", g_pTexture );
				g_pVerticalEffect->SetInt( "g_nDivision", g_nDivision );

				// Apply the technique contained in the effect 
				g_pVerticalEffect->Begin(&cPasses, 0) ;

				for (iPass = 0; iPass < cPasses; iPass++)
				{
					g_pVerticalEffect->BeginPass(iPass) ;

					g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 
						g_listVertex.size(), 0, g_listIndex.size() );


					g_pVerticalEffect->EndPass();
				}
				g_pVerticalEffect->End() ;
			}
		    break;
		case E_Color:
			{
				g_pColorEffect->SetMatrix( "matViewProjection", &g_matProj ) ;
				g_pColorEffect->SetMatrix( "matWorld", &g_matWorld ) ;
				g_pColorEffect->SetMatrix("matView", &g_matView );
				g_pColorEffect->SetTechnique( "vs_2_0_ps_2_0" );
				g_pColorEffect->SetTexture("diffuseMap", g_pTexture );
				g_pColorEffect->SetInt( "g_nDivision", g_nDivision );

				// Apply the technique contained in the effect 
				g_pColorEffect->Begin(&cPasses, 0) ;

				for (iPass = 0; iPass < cPasses; iPass++)
				{
					g_pColorEffect->BeginPass(iPass) ;

					g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 
						g_listVertex.size(), 0, g_listIndex.size() );


					g_pColorEffect->EndPass();
				}
				g_pColorEffect->End() ;
			}
			break;
		case E_ONLY_CONTOURLINE:
			{
				g_pONLY->SetMatrix( "matViewProjection", &g_matProj ) ;
				g_pONLY->SetMatrix( "matWorld", &g_matWorld ) ;
				g_pONLY->SetMatrix("matView", &g_matView );
				g_pONLY->SetTechnique( "vs_2_0_ps_2_0" );
				g_pONLY->SetTexture("diffuseMap", g_pTexture );
				g_pONLY->SetInt( "g_nDivision", g_nDivision );
				g_pONLY->SetInt( "g_nGrads", g_nGrads );

				// Apply the technique contained in the effect 
				g_pONLY->Begin(&cPasses, 0) ;

				for (iPass = 0; iPass < cPasses; iPass++)
				{
					g_pONLY->BeginPass(iPass) ;

					g_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 
						g_listVertex.size(), 0, g_listIndex.size() );


					g_pONLY->EndPass();
				}
				g_pONLY->End() ;
			}
			break;
		default:
		    break;
		}

		//g_pd3dDevice->SetStreamSource( 0, g_pLineVB, 0, sizeof(CUSTOMVERTEX) );

		//g_pd3dDevice->DrawPrimitive(  D3DPT_LINESTRIP, 0, g_listLineVertex.size() -1 );


		// End the scene
		g_pd3dDevice->EndScene();
	}

	// Present the backbuffer contents to the display
	g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}




//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
	case WM_DESTROY:
		Cleanup();
		PostQuitMessage( 0 );
		return 0;
	case WM_KEYUP:									// Has A Key Been Released?
		{
			switch( wParam )
			{
			case VK_ESCAPE:
				{
					Cleanup();
					PostQuitMessage( 0 );
				}
				break;
			case 'L':
				g_bWireFrame = !g_bWireFrame;

				break;
			case VK_F1:
				{
					g_WorkState = E_CONTOUR_LINE;
					g_eyePos = D3DXVECTOR3( -256.0f, 1194.0f,512.0f  );
					g_eyeAt  = D3DXVECTOR3( 0.0f, 0.0f,512.0f  );

				}
				break;
			case VK_F2:
				{
					g_WorkState = E_CROSS_SECTION;

					g_eyePos = D3DXVECTOR3( -1500.0f, 0.0f,512.0f  );
					g_eyeAt  = D3DXVECTOR3( 0.0f, 0.0f,512.0f  );

				}
				break;
			case VK_F3:
				{
					g_eyePos = D3DXVECTOR3( 512.0f, 0.0f,-1500.0f  );
					g_eyeAt  = D3DXVECTOR3( 512.0f, 0.0f,0.0f  );

					g_WorkState = E_VERTICAL_SECTION;
				}
				break;
			case VK_F4:
				{
					g_WorkState = E_Color;
					g_eyePos = D3DXVECTOR3( -256.0f, 1194.0f,512.0f  );
					g_eyeAt  = D3DXVECTOR3( 0.0f, 0.0f,512.0f  );

				}
				break;
			case VK_F5:
				{
					g_WorkState = E_ONLY_CONTOURLINE;
					g_eyePos = D3DXVECTOR3( -256.0f, 1194.0f,512.0f  );
					g_eyeAt  = D3DXVECTOR3( 0.0f, 0.0f,512.0f  );

				}
				break;
			default:
			    break;
			}

			return 0;									// Jump Back
		}
	case WM_KEYDOWN:									// Has A Key Been Released?
		{

			switch( wParam )
			{
			case 'W':
				{
					if( g_WorkState == E_VERTICAL_SECTION || g_WorkState == E_CROSS_SECTION )
						return 0;
					g_eyePos.x += 5;
					g_eyeAt.x  += 5;
				}
				break;
			case 'S':
				{
					if( g_WorkState == E_VERTICAL_SECTION || g_WorkState == E_CROSS_SECTION )
						return 0;
					g_eyePos.x -= 5;
					g_eyeAt.x -= 5;
				}
				break;
			case 'A':
				{
					if( g_WorkState == E_VERTICAL_SECTION || g_WorkState == E_CROSS_SECTION )
						return 0;
					g_eyePos.z += 5;
					g_eyeAt.z += 5;
				}
				break;
			case  'D':
				{
					if( g_WorkState == E_VERTICAL_SECTION || g_WorkState == E_CROSS_SECTION )
						return 0;
					g_eyePos.z -= 5;
					g_eyeAt.z -= 5;
				}
				break;
			case  'H':
				{
					if( g_WorkState == E_VERTICAL_SECTION || g_WorkState == E_CROSS_SECTION )
						return 0;
					g_eyePos.y += 5;
					g_eyeAt.y += 5;
				}
				break;
			case  'J':
				{
					if( g_WorkState == E_VERTICAL_SECTION || g_WorkState == E_CROSS_SECTION )
						return 0;
					g_eyePos.y -= 5;
					g_eyeAt.y -= 5;
				}
				break;
			case 'Z':
				{
					if( g_WorkState == E_VERTICAL_SECTION || g_WorkState == E_CROSS_SECTION )
						return 0;
					if( g_nGrads < 200 )
						g_nGrads += 1;
				}
				break;
			case 'X':
				{
					if( g_WorkState == E_VERTICAL_SECTION || g_WorkState == E_CROSS_SECTION )
						return 0;
					if( g_nGrads > 1 )
						g_nGrads -= 1;
				}
				break;
			case 'C':
				{
					if( g_nDivision < MAP_SIZE )
						g_nDivision += 1;
				}
				break;
			case 'V':
				{
					if( g_nDivision > 1 )
						g_nDivision -= 1;
				}
				break;
			default:
				break;
			}

			return 0;									// Jump Back
		}


	}

	return DefWindowProc( hWnd, msg, wParam, lParam );
}




//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
	// Register the window class

	// Ask The User Which Screen Mode They Prefer
	if (MessageBox(NULL,L"Would You Like To Run In Fullscreen Mode?", L"Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
	{
		fullscreen=FALSE;								// Windowed Mode
	}

	WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_OWNDC, MsgProc, 0L, 0L,
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
		L"HeightMap Sample", NULL };
	RegisterClassEx( &wc );

	HWND hWnd;
	if( !fullscreen )
	{
		hWnd = CreateWindowEx( WS_EX_APPWINDOW | WS_EX_WINDOWEDGE, L"HeightMap Sample", L"HeightMap Sample",
			WS_OVERLAPPEDWINDOW|				// Defined Window Style
			WS_CLIPSIBLINGS |		// Required Window Style
			WS_CLIPCHILDREN, 100, 100, 1024, 768,
			NULL, NULL, wc.hInstance, NULL );

	}
	else
	{

		DEVMODE dmScreenSettings;						// Device Mode
		memset(&dmScreenSettings,0,sizeof(dmScreenSettings));	// Makes Sure Memory's Cleared
		dmScreenSettings.dmSize=sizeof(dmScreenSettings);	// Size Of The Devmode Structure
		dmScreenSettings.dmPelsWidth	= 1024;		// Selected Screen Width
		dmScreenSettings.dmPelsHeight	= 768;		// Selected Screen Height
		dmScreenSettings.dmBitsPerPel	= 32;			// Selected Bits Per Pixel
		dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

		// Try To Set Selected Mode And Get Results.  NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
		if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
		{
			// If The Mode Fails, Offer Two Options.  Quit Or Use Windowed Mode.
			if (MessageBox(NULL,L"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?",L"HeightMap Sample",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
			{
				fullscreen=FALSE;						// Windowed Mode Selected.  Fullscreen = FALSE
			}
			else
			{
				// Pop Up A Message Box Letting User Know The Program Is Closing.
				MessageBox(NULL,L"Program Will Now Close.",L"ERROR",MB_OK|MB_ICONSTOP);
				return FALSE;							// Return FALSE
			}
		}

		ShowCursor(FALSE);								// Hide Mouse Pointer

		hWnd = CreateWindowEx( WS_EX_APPWINDOW, L"HeightMap Sample", L"HeightMap Sample",
			WS_POPUP, 0, 0, 1024, 768,
			NULL, NULL, wc.hInstance, NULL );
	}
	// Create the application's window

	// Initialize Direct3D
	if( SUCCEEDED( InitD3D( hWnd ) ) )
	{
		// Create the scene geometry
		if( SUCCEEDED( InitGeometry() ) )
		{
			// Show the window
			ShowWindow( hWnd, SW_SHOWDEFAULT );
			UpdateWindow( hWnd );

			// Enter the message loop
			MSG msg;
			ZeroMemory( &msg, sizeof(msg) );
			while( msg.message!=WM_QUIT )
			{
				if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
				{
					TranslateMessage( &msg );
					DispatchMessage( &msg );
				}
				else
					Render();
			}
		}
	}

	UnregisterClass( L"HeightMap Sample", wc.hInstance );
	return 0;
}



